/* $Header: npd.c,v 2.2 01/10/02 10:26:06 przybyls Exp $ */

/**********************************************************************/
/*
** FILE NAME:   npd.c
**
** Author:      John DeGood
**
** Comment:     NPD bead power algorithm routines
**
**              Copyright (c) Hewlett-Packard Co. 1993-4
*/
/**********************************************************************/

#include <typedefs.h>
#include <error.h>
#include <p_status.h>
#include <det_ui.h>

/* the 4 zones of the NPD seek algorithm are "< 40", "40-125", "125-250", and "> 250" */
#define NUM_ZONES 4
#define ZONE2MIN  40
#define ZONE3MIN 125
#define ZONE4MIN 250

#define NUM_CONSTANTS 9 /* number of constants in each zone */

static const INT16 npd_init_values[NUM_ZONES][NUM_CONSTANTS] =
{
      /*
      ** These are the ROM-resident initial values of constants used in NPD algorithm.
      ** The NPD has different "zones" of operation.
      ** Each constant can have a different value for each "zone".
      **
      **      0.1 pA                DAC counts                 seconds
      ** ----------------       -----------------       --------------------
      ** a      b       c       d       e       f       t[a]    t[b]    t[c]
      */
        {50,    20,     3,      13,     8,      2,      6,      10,     7},     /* zone 1 */
        {100,   20,     4,      13,     10,     2,      3,      10,     7},     /* zone 2 */
        {500,   200,    40,     13,     10,     2,      4,      10,     5},     /* zone 3 */
        {850,   400,    100,    13,     5,      2,      4,      5,      3}      /* zone 4 */
};

static INT16 NpdDebugIndex;

#pragma SECTION DATA=pfail

/* power-fail RAM-resident copy of constants used in NPD algorithm */
static union
{
        INT16 k[NUM_ZONES][NUM_CONSTANTS];
        INT16 debug[NUM_CONSTANTS*NUM_ZONES];
} npd;

#pragma SECTION UNDO

/* initialize non-volatile RAM-resident NPD variables */
void InitNonvolatileNPD(void)
{
        INT32 i, j;

        for (i = 0; i < NUM_ZONES; i++)
        {
                for (j = 0; j < NUM_CONSTANTS; j++)
                {
                        npd.k[i][j] = npd_init_values[i][j];
                }
        }
}

/**********************************************************************/

/* get index of NPD algorithm constant for debug access */
INT32 GetNPDDebugIndex(void)
{
        return NpdDebugIndex;
}

/**********************************************************************/

/* set index of NPD algorithm constant for debug access */
UI_ERR SetNPDDebugIndex(INT32 index)
{
        if (index < 0)
        {
                return PARAM_TOO_SMALL;
        }
        else if (index >= (NUM_CONSTANTS*NUM_ZONES))
        {
                return PARAM_TOO_LARGE;
        }
        else
        {
                NpdDebugIndex = index;
                return OK;
        }
}

/**********************************************************************/

/* get value of NPD algorithm constant[index] */
INT32 GetNPDDebugParam(void)
{
        return npd.debug[NpdDebugIndex];
}

/**********************************************************************/

/* set value of NPD algorithm constant[index] */
UI_ERR SetNPDDebugParam(INT32 value)
{
        npd.debug[NpdDebugIndex] = (INT16)value;
        return OK;
}

/**********************************************************************/

/* return NPD algorithm constant indexed by target offset(p) and n */
INT32 NPDk (POSITION p, int n)
{
        if (GetNPDTargetOffset(p) < ZONE2MIN)
        {
                return npd.k[0][n];
        }
        else if (GetNPDTargetOffset(p) < ZONE3MIN)
        {
                return npd.k[1][n];
        }
        else if (GetNPDTargetOffset(p) < ZONE4MIN)
        {
                return npd.k[2][n];
        }
        else
        {
                return npd.k[3][n];
        }
}
